home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Astronomy / Moon / Source / shadow.c < prev   
Text File  |  1993-01-19  |  4KB  |  116 lines

  1. /* shadow.c
  2.  * Part of the Moon application for the NeXT computer.
  3.  * Author:  Geoffrey S. Knauth
  4.  * Date:    January 4, 1992
  5.  *
  6.  * Permission to copy this program is hereby granted under the terms
  7.  * of the Free Software Foundation's GNU General Public License.
  8.  */
  9.  
  10. #import <dpsclient/event.h>        /* NXPoint */
  11. #import <dpsclient/psops.h>        /* PSsetgray */
  12. #import "all.h"
  13.  
  14. void DrawMoonShadow        /* draw moon shadow, independent of view */
  15.    (float phase,        /* phase of the moon */
  16.     NXPoint *center,        /* pixel center of moon */
  17.     float xradius,        /* half width of moon in pixels */
  18.     float yradius,        /* half height of moon in pixels */
  19.     int shadowColor)        /* color to use in drawing shadow */
  20. {
  21.   /* DrawMoonShadow is called from within drawSelf:: methods of various
  22.    * view types.  Postscript focus locking and unlocking are outside
  23.    * of this function.
  24.    */
  25.     float yDown, yUp;
  26.     int i, up, down, oneSideHalf, numLeftSidePoints, numRightSidePoints;
  27.     NXPoint *leftSide, *rightSide;    /* storage for lists of NXPoints */
  28.     double d, amp, xscale;
  29.  
  30.   /* the number of points in the top half on one side is
  31.    *    oneSideHalf = center+1..top,
  32.    *    = (top - (center+1) + 1), or (top - center);
  33.    */
  34.     oneSideHalf = rint(yradius);
  35.  
  36.   /* make sure oneSideHalf is >= 0 */
  37.     if (oneSideHalf < 0) oneSideHalf = 0;
  38.  
  39.   /* calculate the number of points on each side
  40.    * remember to add a point for the center
  41.    */
  42.     numLeftSidePoints = numRightSidePoints = 1 + 2 * oneSideHalf;
  43.  
  44.   /* allocate the points */
  45.     leftSide = calloc(numLeftSidePoints, sizeof(NXPoint));
  46.     rightSide = calloc(numRightSidePoints, sizeof(NXPoint));
  47.  
  48.   /* Now iterate from the center to the bottom, filling in information
  49.    *    for the left and right sides.
  50.    * Remember to calculate the region to black out, not whiten.
  51.    * As we fill in points for the bottom half, we know that the points
  52.    *  for the top half will be a mirror image, so we can just copy them.
  53.    */
  54.     xscale = cos(2 * PI * phase);
  55.     for (i = 0,                /* variable controlling loop */
  56.      down = oneSideHalf,        /* index into arrays of NXPoint */
  57.      yDown = yUp = center->y;    /* diverging y values for halves */
  58.      i <= oneSideHalf;        /* stop when bottom half done */
  59.      i++,                /* 0..oneSideHalf-1 */
  60.      down++,            /* oneSideHalf..bottom index */
  61.      yDown -= 1.,            /* float y for drawing bottom half */
  62.      yUp += 1.)            /* float y for drawing upper half */
  63.     {
  64.     if ((d = i / yradius) > 1.0)
  65.         d = 1.0;
  66.     amp = xradius * cos(asin(d));    /* d > 1.0 yields NaN (not a number) */
  67.  
  68.     /* 0.0 = new moon, 0.5 full moon, 1.0 = next new moon */
  69.     if (phase < 0.5) {                    /* waxing */
  70.         leftSide[down].x  = center->x - amp;
  71.         rightSide[down].x = center->x + xscale * amp;
  72.     } else {                        /* waning */
  73.         rightSide[down].x = center->x + amp;
  74.         leftSide[down].x  = center->x - xscale * amp;
  75.     }
  76.     leftSide[down].y = rightSide[down].y = yDown;
  77.  
  78.     if (i) {        /* # points offset downward from center */
  79.         up = down - 2 * i;
  80.         leftSide[up].x  = leftSide[down].x;
  81.         rightSide[up].x = rightSide[down].x;
  82.         leftSide[up].y = rightSide[up].y = yUp;
  83.     }
  84.     }
  85.  
  86.   /* Now iterate again from the top, this time actually creating
  87.    *    a path clockwise around the points just calculated.
  88.    */
  89.     PSnewpath();
  90.     PSmoveto(rightSide[0].x, rightSide[0].y);
  91.  
  92.   /* Go down the right side, starting with the second point, because we
  93.    * just moved to the top point.
  94.    */
  95.     for (i = 1; i < numRightSidePoints; i++)
  96.     PSlineto(rightSide[i].x, rightSide[i].y);
  97.  
  98.   /* Now go up the left side, starting again with the second point, because
  99.    * we just reached the bottom, and stop one short of the top, because we
  100.    * started with the top when we started down in the first place.
  101.    */
  102.     for (i = numLeftSidePoints - 2; i > 0; i--)
  103.     PSlineto(leftSide[i].x, leftSide[i].y);
  104.  
  105.     PSclosepath();
  106.  
  107.   /* draw the moon shadow, that part of the moon hidden from the sun */
  108.     PSsetgray(shadowColor);
  109.     PSfill();
  110.  
  111.   /* deallocate the points */
  112.     free((char *) leftSide);
  113.     free((char *) rightSide);
  114. }
  115.  
  116.